/*
 * LiquidBounce Hacked Client
 * A free open source mixin-based injection hacked client for Minecraft using Minecraft Forge.
 * https://github.com/CCBlueX/LiquidBounce/
 */
package net.ccbluex.liquidbounce.features.module.modules.exploit

import net.ccbluex.liquidbounce.api.MinecraftVersion
import net.ccbluex.liquidbounce.api.minecraft.network.IPacket
import net.ccbluex.liquidbounce.event.EventTarget
import net.ccbluex.liquidbounce.event.PacketEvent
import net.ccbluex.liquidbounce.event.UpdateEvent
import net.ccbluex.liquidbounce.features.module.Module
import net.ccbluex.liquidbounce.features.module.ModuleCategory
import net.ccbluex.liquidbounce.features.module.ModuleInfo
import net.ccbluex.liquidbounce.utils.timer.TimeUtils
import net.ccbluex.liquidbounce.value.IntegerValue

@ModuleInfo(name = "PingSpoof", description = "Spoofs your ping to a given value.", category = ModuleCategory.EXPLOIT, supportedVersions = [MinecraftVersion.MC_1_8])
class PingSpoof : Module() {

    private val minDelayValue: IntegerValue = object : IntegerValue("MinDelay", 500, 0, 5000) {
        override fun onChanged(oldValue: Int, newValue: Int) {
            val maxDelayValue = maxDelayValue.get()

            if (maxDelayValue < newValue)
                set(maxDelayValue)
        }
    }

    private val maxDelayValue: IntegerValue = object : IntegerValue("MaxDelay", 1000, 0, 5000) {
        override fun onChanged(oldValue: Int, newValue: Int) {
            val minDelayValue = minDelayValue.get()

            if (minDelayValue > newValue)
                set(minDelayValue)
        }
    }

    private val packetQueue = hashMapOf<IPacket, Long>()

    override fun onDisable() {
        packetQueue.clear()
    }

    @EventTarget
    fun onPacket(event: PacketEvent) {
        val packet = event.packet

        if ((classProvider.isCPacketKeepAlive(packet) || classProvider.isCPacketClientStatus(packet))
                && !(mc.thePlayer!!.isDead || mc.thePlayer!!.health <= 0) && !packetQueue.containsKey(packet)) {
            event.cancelEvent()

            synchronized(packetQueue) {
                packetQueue[packet] = System.currentTimeMillis() + TimeUtils.randomDelay(minDelayValue.get(), maxDelayValue.get())
            }
        }
    }

    @EventTarget
    fun onUpdate(event: UpdateEvent) {
        synchronized(packetQueue) {
            packetQueue.filter {
                it.value >= System.currentTimeMillis()
            }.forEach { (packet, time) ->
                mc.netHandler.addToSendQueue(packet)
                packetQueue.remove(packet, time)
            }
        }
    }

}